"use strict";

const formatDefaultConfig = {
    /** 时间戳 */
    timeStamp: "",
    /** 分隔符(传入 zh 显示年月日) */
    spe: "/",
    /** 是否返回日期 */
    isDate: true,
    /** 是否返回时间 */
    isTime: true
};
const weeksMap = {
    0: "星期日",
    1: "星期一",
    2: "星期二",
    3: "星期三",
    4: "星期四",
    5: "星期五",
    6: "星期六"
};

/**
 * @author zhuzhaofeng
 * 常用工具类
 * @dateTime 2019年9月11日10:48:49
 */
class CommonUtils {
    constructor() {}
    /**
     * 是否是数组
     * @param val 需要判断的值
     * @returns {boolean}
     */
    isArray(val) {
        return toString.call(val) === "[object Array]";
    }

    /**
     * 是否是字符串
     * @param val
     * @returns {boolean}
     */
    isString(val) {
        return typeof val === "string";
    }

    /**
     * 是否是数字
     * @param val
     * @returns {boolean}
     */
    isNumber(val) {
        return typeof val === "number";
    }

    /**
     * 是否是方法
     * @param val
     * @returns {boolean}
     */
    isFunction(val) {
        return toString.call(val) === "[object Function]";
    }

    /**
     * 是否是undefined
     * @param val
     * @returns {boolean}
     */
    isUndefined(val) {
        return typeof val === "undefined";
    }

    /**
     * 是否是对象
     * @param val
     * @returns {boolean}
     */
    isObject(val) {
        return val !== null && typeof val === "object";
    }

    /**
     * 是否是移动端
     * @returns {boolean}
     */
    isMobile() {
        const sUserAgent = navigator.userAgent.toLowerCase();
        return sUserAgent.match(
            /(iphone|ipad|ipod|android|windows ce|windows mobile)/i
        );
    }

    /**
     * 去除字符串左边空格
     * @param {String} str 需要去除空格的字符串
     */
    trimL(str = "") {
        return str.replace(/(^\s*)/g, "");
    }
    /**
     * 去除字符串右边空格
     * @param {String} str 需要去除空格的字符串
     */
    trimR(str = "") {
        return str.replace(/(\s*$)/g, "");
    }

    /**
     * 去除字符串中所有空格
     * @param {String} str 需要去除空格的字符串
     */
    trimAll(str = "") {
        return str.replace(/\s*/g, "");
    }

    /**
     * 去除字符串左右两边空格
     * @param {String} str 需要去除空格的字符串
     */
    trim(str = "") {
        return str.replace(/^\s*|\s*$/g, "");
    }
    /**
     * @description 字符串是否为空
     */
    isEmpty(str = "") {
        return str && this.trim(str).length < 1
    }
    /**
     * @description 字符串是否不为空
     */
    isNotEmpty(str = "") {
        return str && this.trim(str).length > 0
    }

    /**
     * 获取当前时间戳
     * @returns {number} 当前时间戳
     */
    unix() {
        return new Date().getTime();
    }
    /**
     * 获取今天0点0分0秒的时间戳
     * @returns {number} 时间戳
     */
    todayUnix() {
        let date = new Date();
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);
        return date.getTime();
    }
    /**
     * 获取今年1月1日0点0分0秒的时间戳
     * @returns {number} 时间戳
     */
    yearUnix() {
        let date = new Date();
        date.setMonth(0);
        date.setDate(1);
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);
        return date.getTime();
    }
    /**
     *
     * 根据时间戳获取星期
     * @param {String} timeStamp 时间戳
     */
    formatWeek(timeStamp = this.unix()) {
        let date = new Date(timeStamp);
        return weeksMap[date.getDay()];
    }
    /**
     * 将时间戳格式化为对象 如下
     *   {
     *      year: "年",
     *      month: "月",
     *      day: "日",
     *      hours: "时",
     *      minute: "分",
     *      second: "秒",
     *      quarter: "季度",
     *      week: "星期"
     *   }
     */
    formatObject(timeStamp = this.unix()) {
        let week = this.formatWeek(timeStamp);
        let date = new Date(timeStamp);
        let year = date.getFullYear();
        let month = date.getMonth() + 1;
        month = month < 10 ? "0" + month : month;
        let day = date.getDate();
        day = day < 10 ? "0" + day : day;
        let hours = date.getHours();
        hours = hours < 10 ? "0" + hours : hours;
        let minute = date.getMinutes();
        let second = date.getSeconds();
        minute = minute < 10 ? "0" + minute : minute;
        second = second < 10 ? "0" + second : second;
        let quarter = Math.floor((date.getMonth() + 4) / 3);
        return {
            year,
            month,
            day,
            hours,
            minute,
            second,
            quarter,
            week
        };
    }

    /**
     *
     * 获取日期
     * @param { String } timeStamp 需要格式化的时间戳
     * @param { String } spe 分隔符(传入 zh 显示年月日)
     */
    formatDate(spe = "/", timeStamp = this.unix()) {
        spe = spe.toLowerCase();
        let date = this.formatObject(timeStamp);
        let resultDate = `${date.year}${spe}${date.month}${spe}${date.day}`;
        if (spe === "zh") {
            resultDate = `${date.year}年${date.month}月${date.day}日`;
        }
        return resultDate;
    }
    /**
     * 获取时间
     * @param { String } timeStamp 需要格式化的时间戳
     */
    formatTime(timeStamp = this.unix()) {
        let date = this.formatObject(timeStamp);
        return `${date.hours}:${date.minute}:${date.second}`;
    }

    /**
     *  根据参数格式化为自定义时间
     * @param {formatDefaultConfig} params 配置参数
     */
    format(params = formatDefaultConfig) {
        params = Object.assign({}, formatDefaultConfig, params);
        // 删除多余参数
        for (const key in params) {
            if (!formatDefaultConfig.hasOwnProperty(key)) {
                delete params[key];
            }
        }
        if (params.timeStamp === "") {
            params.timeStamp = this.unix();
        }
        params.spe = params.spe.toLowerCase();
        let date = this.formatObject(params.timeStamp);
        let resultDate = `${date.year}${params.spe}${date.month}${params.spe}${date.day}`;
        if (params.spe === "zh") {
            resultDate = `${date.year}年${date.month}月${date.day}日`;
        }
        let resultTime = `${date.hours}:${date.minute}:${date.second}`;
        params.isDate ? true : (resultDate = "");
        params.isTime ? true : (resultTime = "");
        return this.trim(`${resultDate} ${resultTime}`);
    }
    /**
     * 转换时间
     *  1分钟以前 显示 刚刚
     * 	1分钟~1小时 显示xx分钟前
     * 	1小时~1天 显示 xx小时前
     * 	1天~1个月(31天)前 显示 xx天前
     *  大于1个月 显示 xx年xx月xx日
     */
    convertTime(timeStamp = this.unix()) {
        let now = this.unix();
        let today = this.todayUnix();
        let year = this.yearUnix();
        // 转换为秒级时间戳
        let timer = (now - timeStamp) / 1000;
        if (timer <= 0) {
            return "刚刚";
        } else if (Math.floor(timer / 60) <= 0) {
            return "刚刚";
        } else if (timer < 3600) {
            return `${Math.floor(timer / 60)}分钟前`;
        } else if (timer > 3600 && timeStamp - today >= 0) {
            return `${Math.floor(timer / 3600)}小时前`;
        } else if (timer / 86400 <= 31) {
            return `${Math.ceil(timer / 86400)}天前`;
        } else {
            return this.formatDate("-", timeStamp);
        }
    }

    /**
     * 递归遍历json 生成树形
     * @param jsonArr 需要遍历的json数组
     * @param selfIdField 每条数据id字段
     * @param parentIdField 每条数据父级id字段
     * @param parentld 最顶级 父级id值
     * @returns {[]|Array}
     */
    convertToTreeData(
        jsonArr = [],
        selfIdField = "id",
        parentIdField = "parentId",
        parentld = ""
    ) {
        let result = [];
        if (this.isArray(jsonArr) && this.isString(parentIdField)) {
            if (jsonArr.length < 1) {
                return [];
            } else {
                for (const val of jsonArr) {
                    if (val[`${parentIdField}`] === parentld) {
                        let obj = {};
                        for (const key in val) {
                            obj[`${key}`] = val[`${key}`];
                        }
                        let children = this.convertToTreeData(
                            jsonArr,
                            selfIdField,
                            parentIdField,
                            obj[`${selfIdField}`]
                        );
                        if (children.length > 0) {
                            obj.children = children;
                        }
                        result.push(obj);
                    }
                }
            }
        } else {
            throw "传入参数格式不正确";
        }
        return result;
    }
    /**
     * 函数防抖(连续操作只执行最后一次)
     * @param fn 函数
     * @param delay 间隔
     * @returns {Function}
     */
    debounce(fn, delay = 200) {
        let timer = null;
        return (...args) => {
            clearTimeout(timer);
            timer = setTimeout(() => {
                fn.apply(this, args);
            }, delay);
        };
    }
    /**
     * 函数节流
     * @param fn 函数
     * @param delay 间隔
     * @returns {Function}
     */
    throttle(fn, delay = 200) {
        let flag = false;
        return (...args) => {
            if (flag) return;
            flag = true;
            setTimeout(() => {
                fn.apply(this, args);
                flag = false;
            }, delay);
        };
    }
    /**
     * 单继承 属性复制
     * @param {objcet} target 目标对象
     * @param {Object} source 源对象
     * @returns {object} 合并后的对象
     */
    extend(target, source) {
        try {
            return Object.assign(target, source);
        } catch (err) {
            for (let property in source) {
                target[property] = source[property];
            }
            return target;
        }
    }
}

/**导出 */
export default new CommonUtils();
